package simple.util;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;
import java.nio.charset.StandardCharsets;

public class FTPUtil {

    /**
     * 获取FTPClient对象
     *
     * @param ftpHost     服务器IP
     * @param ftpPort     服务器端口号
     * @param ftpUserName 用户名
     * @param ftpPassword 密码
     * @return FTPClient
     */
    public static FTPClient getFTPClient(String ftpHost, int ftpPort,
                                         String ftpUserName, String ftpPassword) throws IOException {
        FTPClient ftp;
        ftp = new FTPClient();
        // 连接FPT服务器,设置IP及端口
        ftp.connect(ftpHost, ftpPort);
        // 设置用户名和密码
        ftp.login(ftpUserName, ftpPassword);
        // 设置连接超时时间,5000毫秒
        ftp.setConnectTimeout(50000);
        // 设置中文编码集，防止中文乱码
//        ftp.setControlEncoding("UTF-8");
        if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
            ftp.disconnect();
        }
        return ftp;
    }

    /**
     * 关闭FTP方法
     *
     * @param ftp 被关闭的ftp
     */
    public static void closeFTP(FTPClient ftp) {

        try {
            ftp.logout();
        } catch (Exception e) {
            System.err.println("FTP关闭失败");
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    System.err.println("FTP关闭失败");
                }
            }
        }
    }

    /**
     * 下载FTP下指定文件
     *
     * @param ftp      FTPClient对象
     * @param filePath FTP文件路径
     * @param fileName 文件名
     * @param downPath 下载保存的目录
     * @return true 标示下载成功，false标示下载失败
     */
    public boolean downLoadFTP(FTPClient ftp, String filePath, String fileName,
                               String downPath) throws IOException {
        // 默认失败
        boolean flag = false;
        // 跳转到文件目录
        ftp.changeWorkingDirectory(filePath);
        // 获取目录下文件集合
        ftp.enterLocalPassiveMode();
        FTPFile[] files = ftp.listFiles();
        for (FTPFile file : files) {
            // 取得指定文件并下载
            if (file.getName().equals(fileName)) {
                File downFile = new File(downPath, file.getName());
                OutputStream out = new FileOutputStream(downFile);
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(out);
                // 绑定输出流下载文件,需要设置编码集，不然可能出现文件为空的情况
                flag = ftp.retrieveFile(new String(file.getName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1), bufferedOutputStream);
                // 下载成功删除文件,看项目需求
                // ftp.deleteFile(new String(fileName.getBytes("UTF-8"),"ISO-8859-1"));
                out.flush();
                out.close();
                bufferedOutputStream.close();
                if (flag) {
                    System.out.println("下载成功");
                } else {
                    System.err.println("下载失败");
                }
            }
        }
        return flag;
    }

    /**
     * FTP文件上传工具类
     *
     * @param ftp      ftp连接对象
     * @param filePath 被上传的文件的本机路径
     * @param ftpPath  上传到ftp的路径
     * @return true标示上传成功，false标示上传失败
     */
    public boolean uploadFile(FTPClient ftp, String filePath, String ftpPath) throws IOException {
        boolean flag;
        InputStream in = null;
        // 设置PassiveMode传输
        ftp.enterLocalPassiveMode();
        //设置二进制传输，使用BINARY_FILE_TYPE，ASC容易造成文件损坏
        ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
        //判断FPT目标文件夹时候存在不存在则创建
        if (!ftp.changeWorkingDirectory(ftpPath)) {
            ftp.makeDirectory(ftpPath);
        }
        //跳转目标目录
        ftp.changeWorkingDirectory(ftpPath);

        //上传文件
        File file = new File(filePath);
        in = new FileInputStream(file);
        String tempName = ftpPath.concat(File.separator).concat(file.getName());
        flag = ftp.storeFile(new String(tempName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1), in);
        if (flag) {
            System.out.println("上传成功");
        } else {
            System.err.println("上传失败");
        }
        return flag;
    }

    /**
     * 递归进入指定目录
     *
     * @param ftpClient ftp连接对象
     * @param path      要进入的目录的相对路径
     * @param regex     分隔目录的分隔符
     * @return true表示进入成功，false表示进入失败
     */
    public static boolean changeDir(FTPClient ftpClient, String path, String regex) throws IOException {
        if (path.startsWith(regex)) {
            path = path.substring(regex.length());
        }
        if (path.endsWith(regex)) {
            path = path.substring(0, path.length() - regex.length());
        }
        String[] split = path.split(regex);
        boolean flag = false;
        for (String str : split) {
            flag = ftpClient.changeWorkingDirectory(str);
        }
        return flag;
    }
}
